package com.ccf.business.etl.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.ccf.business.etl.model.dto.FlowInfoDTO;
import com.ccf.business.etl.model.vo.FlowVO;
import com.ccf.business.etl.service.IFlowService;
import com.ccf.business.etl.service.ITaskService;
import com.component.api.excepiton.ComponentException;
import com.component.api.model.param.TableColumn;
import com.ccf.business.etl.model.Flow;
import com.ccf.business.etl.model.Task;
import com.common.model.exception.FlowAnalysisException;
import com.common.model.pojo.Keyword;
import com.common.model.pojo.Query;
import com.common.model.result.PageResult;
import com.common.model.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 流程表
 *
 * @author ccf
 * @date 2021-11-29 18:02:10
 */
@Slf4j
@RestController
@RequestMapping("/flow")
@Api(tags = "流程表")
public class FlowController {
    @Autowired
    private IFlowService flowService;
    @Autowired
    private ITaskService taskService;

    /**
     * 列表
     */
    @ApiOperation(value = "分页查询列表")
    @GetMapping
    public PageResult list(Query query) {

        PageResult<Flow> list = flowService.findList(query);
        Set<String> ids = list.getDatas().stream().map(e -> e.getId()).collect(Collectors.toSet());
        List<Task> jobByFlowIds = taskService.getTaskByFlowIds(ids);
        Map<String, List<Task>> flowJobs =
                jobByFlowIds.stream().collect(Collectors.groupingBy(Task::getFlowId));
        list.getDatas().stream().forEach(e-> {
            if (flowJobs.containsKey(e.getId())) {
                e.setStatus(Flow.YES);
            } else {
                e.setStatus(Flow.NO);
            }
        });
        return list;
    }


    /**
     * 查询
     */
    @ApiOperation(value = "查询")
    @GetMapping("/{id}")
    public Result getById(@PathVariable String id) {
        FlowInfoDTO model = flowService.getDetailById(id);
        return Result.succeed(model, "查询成功");
    }

    /**
     * 新增or更新
     */
    @ApiOperation(value = "保存")
    @PostMapping
    public Result save(@RequestBody Flow flow) {
        if (flowService.isExistNameAndDelFlag(flow.getId(), flow.getName())){
            return Result.failed("名称已存在");
        }
        try {
            String flowId = flowService.saveAndAnalysis(flow);
            return Result.succeed(flowId, "保存成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("保存失败，格式错误");
        }

    }

    /**
     * 测试运行
     *  data数据可能很大 这里不用get请求
     */
    @ApiOperation(value = "测试运行")
    @ApiImplicitParams({
            @ApiImplicitParam(name="id", value = "如果还没保存，可以不传，查询状态时传返回的id", required = false),
            @ApiImplicitParam(name="data", value = "流程数据", required = true),
    })
    @PostMapping("/test")
    public Result test(@RequestBody FlowVO flowVO) {
        try {
            Flow res  = flowService.testRunning(flowVO.getId(), flowVO.getData());
            return Result.succeed(res,"测试运行开始，请等待运行结束");
        } catch (FlowAnalysisException e) {
            e.printStackTrace();
            return Result.failed("运行失败:" + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("运行失败，请检查日志");
        }
    }
    /**
     * 测试运行停止
     *  data数据可能很大 这里不用get请求
     */
    @ApiOperation(value = "停止测试运行")
    @ApiImplicitParam(name="id", value = "如果还没保存，可以不传，查询状态时传返回的id", required = true)
    @PostMapping("/stop")
    public Result stopTest(@RequestBody FlowVO flowVO) {
        try {
            boolean b  = flowService.stopTest(flowVO.getId());
            return Result.succeed(b,"停止成功");
        } catch (FlowAnalysisException e) {
            e.printStackTrace();
            return Result.failed("停止失败:" + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("停止失败，请检查日志");
        }
    }

    /**
     * 运行
     *  data数据可能很大 这里不用get请求
     */
    @ApiOperation(value = "运行")
    @PostMapping("/running")
    public Result running(@RequestBody FlowVO flowVO) {
        try {
            String jobId = flowService.running(flowVO.getId());
            return Result.succeed(jobId,"运行开始");
        } catch (FlowAnalysisException e) {
            e.printStackTrace();
            return Result.failed("运行失败:" + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("运行失败，请检查日志");
        }
    }

    /**
     * 选择列
     */
    @ApiOperation(value = "选择字段")
    @PostMapping("/selectFields")
    public Result selectFields(@RequestBody FlowVO flowVO) {
        if (StrUtil.isBlank(flowVO.getData()) || StrUtil.isBlank(flowVO.getCurrentId()) ){
            Result.failed("请求参数为空");
        }
        Map<String, List<TableColumn>> columnList = new HashMap<>();
        try {
            columnList = flowService.selectFields(flowVO.getData(), flowVO.getCurrentId());
            //前端要的过滤
            List<Keyword> keywords = flowVO.getKeywords();
            if (CollUtil.isNotEmpty(keywords) &&  keywords.get(0) != null){
                final String keywordStr = keywords.get(0).getKeyword();

                for (String key : columnList.keySet()) {
                    List<TableColumn> value = columnList.get(key);
                    value = value.stream().filter(e-> e.getColumnName().contains(keywordStr))
                            .collect(Collectors.toList());
                    columnList.put(key, value);
                }
            }

            return Result.succeed(columnList,"操作成功");
        } catch (FlowAnalysisException e) {
            e.printStackTrace();
            return Result.failed(columnList, e.getMessage());
        } catch (ComponentException e) {
            e.printStackTrace();
            return Result.failed(columnList, e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed(columnList,"错误："+e.getMessage());
        }
    }

    /**
     * 删除
     */
    @ApiOperation(value = "删除")
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable String id) {
        //批量删除
        if (StrUtil.contains(id, ",")){
            String[] ids = StrUtil.split(id, ",");
            flowService.removeByIds(Arrays.stream(ids).collect(Collectors.toList()));
        } else {

            flowService.removeById(id);
        }
        return Result.succeed("删除成功");
    }


    /**
     * 删除校验接口
     */
    @ApiOperation(value = "删除校验接口")
    @GetMapping("/{id}/validate")
    public Result deleteValidate(@PathVariable String id) {
        if(StrUtil.isEmpty(id)) {
            return Result.failed("请选择需要删除校验的数据");
        }
        return Result.succeed(flowService.deleteValidate(id));
    }

    /**
     * 查询流程状态接口
     */
    @ApiOperation(value = "查询流程状态接口", notes = "当流程是运行中时(返回true)需要轮询调用")
    @GetMapping("/{id}/status")
    public Result status(@PathVariable String id) {
        if(StrUtil.isEmpty(id)) {
            return Result.succeed(false, "id不能为空");
        }
        return Result.succeed(flowService.status(id), "查询成功");
    }
}
